{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# identifying impersonator by identifying author style"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:19:24.357292Z",
     "start_time": "2018-07-28T16:19:17.927185Z"
    }
   },
   "outputs": [],
   "source": [
    "import tweepy\n",
    "\n",
    "# Consumer keys and access tokens, used for OAuth\n",
    "api_key = 'g5uPIpw80nULQI1gfklv2zrh4'\n",
    "api_secret = 'cOWvNWxYvPmEZ0ArZVeeVVvJu41QYHdUS2GpqIKtSQ1isd5PJy'\n",
    "access_token = '49722956-TWl8J0aAS6KTdcbz3ppZ7NfqZEmrwmbsb9cYPNELG'\n",
    "access_secret = '3eqrVssF3ppv23qyflyAto8wLEiYRA8sXEPSghuOJWTub'\n",
    "\n",
    "\n",
    "# OAuth process, using the keys and tokens\n",
    "auth = tweepy.OAuthHandler(api_key, api_secret)\n",
    "auth.set_access_token(access_token, access_secret)\n",
    "\n",
    "# Creation of the actual interface, using authentication\n",
    "api = tweepy.API(auth)\n",
    "my_tweets, other_tweets = [], []\n",
    "\n",
    "to_get = 500\n",
    "for status in tweepy.Cursor(api.user_timeline, screen_name='@prof_oz').items():\n",
    "    text = status._json['text']\n",
    "    if text[:3] != 'RT ':  # we don't want retweets because they didn't author those!\n",
    "        my_tweets.append(text)\n",
    "    else:\n",
    "        other_tweets.append(text)\n",
    "    to_get -= 1\n",
    "    if to_get <=0:\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:19:24.376155Z",
     "start_time": "2018-07-28T16:19:24.363676Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(131, 151)"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(real_tweets), len(other_tweets)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:19:26.742366Z",
     "start_time": "2018-07-28T16:19:26.731981Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(u'@stanleyyork Definitely check out the Grand Bazaar as well as a tour around the Mosques and surrounding caf\\xe9s / sho\\u2026 https://t.co/ETREtznTgr',\n",
       " u'RT @SThornewillvE: This weeks @superdatasci podcast has a lot of really interesting talk about #featureengineering, with @Prof_OZ, the auth\\u2026')"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "real_tweets[0], other_tweets[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:19:26.906762Z",
     "start_time": "2018-07-28T16:19:26.901270Z"
    }
   },
   "outputs": [],
   "source": [
    "import pandas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:22:46.363817Z",
     "start_time": "2018-07-28T16:22:46.352004Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(386, 2)"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pandas.DataFrame({'text': my_tweets+other_tweets, 'is_mine': [True]*len(my_tweets)+[False]*len(other_tweets)})\n",
    "\n",
    "df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:22:46.527295Z",
     "start_time": "2018-07-28T16:22:46.505474Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>is_mine</th>\n",
       "      <th>text</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>True</td>\n",
       "      <td>@stanleyyork Definitely check out the Grand Ba...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>True</td>\n",
       "      <td>12 Exciting Ways You Can Use Voice-Activated T...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   is_mine                                               text\n",
       "0     True  @stanleyyork Definitely check out the Grand Ba...\n",
       "1     True  12 Exciting Ways You Can Use Voice-Activated T..."
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:22:46.684812Z",
     "start_time": "2018-07-28T16:22:46.660046Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>is_mine</th>\n",
       "      <th>text</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>384</th>\n",
       "      <td>False</td>\n",
       "      <td>RT @Variety: BREAKING: #TheInterview will be s...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>385</th>\n",
       "      <td>False</td>\n",
       "      <td>RT @ProfLiew: Let's all congratulate Elizabeth...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     is_mine                                               text\n",
       "384    False  RT @Variety: BREAKING: #TheInterview will be s...\n",
       "385    False  RT @ProfLiew: Let's all congratulate Elizabeth..."
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.tail(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:14.177072Z",
     "start_time": "2018-07-28T16:23:14.166685Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "np.random.seed(10)\n",
    "\n",
    "remove_n = int(.1 * df.shape[0])  # remove 10% of rows for validation set\n",
    "\n",
    "drop_indices = np.random.choice(df.index, remove_n, replace=False)\n",
    "validation_set = df.iloc[drop_indices]\n",
    "training_set = df.drop(drop_indices)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:21.305232Z",
     "start_time": "2018-07-28T16:23:21.295298Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((38, 2), (348, 2))"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "validation_set.shape, training_set.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:26.278177Z",
     "start_time": "2018-07-28T16:23:26.272552Z"
    }
   },
   "outputs": [],
   "source": [
    "X, y = training_set['text'], training_set['is_mine']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:38:00.656695Z",
     "start_time": "2018-07-28T16:38:00.649528Z"
    }
   },
   "outputs": [],
   "source": [
    "from sklearn.feature_extraction.text import CountVectorizer\n",
    "from sklearn.pipeline import Pipeline, FeatureUnion, make_pipeline\n",
    "from sklearn.naive_bayes import MultinomialNB\n",
    "from sklearn.model_selection import GridSearchCV"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:27.373290Z",
     "start_time": "2018-07-28T16:23:27.363943Z"
    }
   },
   "outputs": [],
   "source": [
    "pipeline_parts = [\n",
    "    ('vectorizer', CountVectorizer()),\n",
    "    ('classifier', MultinomialNB())\n",
    "    \n",
    "]\n",
    "simple_pipeline = Pipeline(pipeline_parts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:30.347205Z",
     "start_time": "2018-07-28T16:23:27.563077Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GridSearchCV(cv=None, error_score='raise',\n",
       "       estimator=Pipeline(memory=None,\n",
       "     steps=[('vectorizer', CountVectorizer(analyzer=u'word', binary=False, decode_error=u'strict',\n",
       "        dtype=<type 'numpy.int64'>, encoding=u'utf-8', input=u'content',\n",
       "        lowercase=True, max_df=1.0, max_features=None, min_df=1,\n",
       "        ngram_range=(1, 1), pre...one, vocabulary=None)), ('classifier', MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True))]),\n",
       "       fit_params=None, iid=True, n_jobs=1,\n",
       "       param_grid={'vectorizer__ngram_range': [(1, 1), (1, 3), (1, 5)], 'vectorizer__analyzer': ['word', 'char', 'char_wb']},\n",
       "       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',\n",
       "       scoring=None, verbose=0)"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simple_grid_search_params = {\n",
    "    \"vectorizer__ngram_range\": [(1, 1), (1, 3), (1, 5)],\n",
    "    \"vectorizer__analyzer\": [\"word\", \"char\", \"char_wb\"],\n",
    "}\n",
    "\n",
    "grid_search = GridSearchCV(simple_pipeline, simple_grid_search_params)\n",
    "\n",
    "grid_search.fit(X, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:30.361252Z",
     "start_time": "2018-07-28T16:23:30.351794Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.896551724137931"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grid_search.best_score_  # best cross validated accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:35.595044Z",
     "start_time": "2018-07-28T16:23:35.589701Z"
    }
   },
   "outputs": [],
   "source": [
    "model = grid_search.best_estimator_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:23:35.771116Z",
     "start_time": "2018-07-28T16:23:35.759996Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2.56519064e-07, 9.99999743e-01]])"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# % False, % True\n",
    "model.predict_proba([my_tweets[0]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:24:13.276834Z",
     "start_time": "2018-07-28T16:24:13.262573Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9210526315789473"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "accuracy_score(model.predict(validation_set['text']), validation_set['is_mine'])  # accuracy on validation set. Very good!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-28T16:24:47.724976Z",
     "start_time": "2018-07-28T16:24:47.718357Z"
    }
   },
   "outputs": [],
   "source": [
    "# this model can now be used to monitor timelines to spot if an author's style has changed or is being hacked"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
